// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
#pragma once
#include "SequentialReaderWriter.h"

// Processing agent that serializes simultaneous file read and write operations.
// This is somewhat experimental, and feedback is welcome.

class FileReaderWriter : public SequentialReaderWriter<Platform::String^, void, std::tuple<>, Platform::String^>
{
public:
    FileReaderWriter(Windows::Storage::StorageFolder^ folder, Platform::String^ fileName, Windows::Storage::CreationCollisionOption fileCreationOption) : m_folder(folder), m_fileName(fileName), m_fileCreationOption(fileCreationOption)
    {
    }

    FileReaderWriter(FileReaderWriter const&) = delete;
    FileReaderWriter const& operator=(FileReaderWriter const&) = delete;

protected:
    virtual concurrency::task<void> InternalRead(const std::tuple<std::tuple<>, concurrency::task_completion_event<Platform::String^>>& t)
    {
        auto tce = std::get<1>(t);
        return concurrency::create_task(m_folder->GetFileAsync(m_fileName)).then([](Windows::Storage::StorageFile^ file)
        {
            return concurrency::create_task(Windows::Storage::FileIO::ReadTextAsync(file));

        }).then([tce](concurrency::task<Platform::String^> previousTask)
        {
            assert(IsBackgroundThread());
            try
            {
                tce.set(previousTask.get());
            }
            catch (...)
            {
                tce.set_exception(std::current_exception());
            }
        });
    }

    virtual concurrency::task<void> InternalWrite(const std::tuple<Platform::String^, concurrency::task_completion_event<void>>& t)
    {
        auto text = std::get<0>(t);
        auto tce = std::get<1>(t);
        return concurrency::create_task(m_folder->CreateFileAsync(m_fileName, m_fileCreationOption)).then([text](Windows::Storage::StorageFile^ file)
        {
            return concurrency::create_task(Windows::Storage::FileIO::WriteTextAsync(file, text));

        }).then([tce](concurrency::task<void> previousTask)
        {
            assert(IsBackgroundThread());
            try
            {
                previousTask.get();
                tce.set();
            }
            catch (...)
            {
                tce.set_exception(std::current_exception());
            }
        });
    }

private:
    Windows::Storage::StorageFolder^ m_folder;
    Platform::String^ m_fileName;
    Windows::Storage::CreationCollisionOption m_fileCreationOption;
};